const gWebSocketMgr = {
  socketInfoList: []
};

export function clearWebSocket() {
  closeWebSocket();
  gWebSocketMgr.socketInfoList = [];
}

export function closeWebSocket(url, protocol) {
  if(url) {
    let realUrl = url;
    if(realUrl.startsWith('/')) {
      let loc = window.location;
      if (loc.protocol === "https:") {
        realUrl = "wss:";
      } else {
        realUrl = "ws:";
      }
      realUrl += "//" + loc.host + url;
    }

    if(protocol == '') protocol == null;
    for(let i=0;i<gWebSocketMgr.socketInfoList.length;i++) {
      if(gWebSocketMgr.socketInfoList[i].url == realUrl && gWebSocketMgr.socketInfoList[i].protocol == protocol) {
        let socketInfo = gWebSocketMgr.socketInfoList[i];
        if(socketInfo.connected) {
          socketInfo.socket.close();
        }
        break;
      }
    }
  } else {
    let socketInfo;
    while((socketInfo = gWebSocketMgr.socketInfoList.pop()) != null) {
      if(socketInfo.connected) {
        socketInfo.socket.close();
      }
    }
  }
}

export function createWebSocket(url, protocol) {
  if(typeof(WebSocket) == 'undefined') {
    return null;
  }
  let realUrl = url;
  if(realUrl.startsWith('/')) {
    let loc = window.location;
    if (loc.protocol === "https:") {
      realUrl = "wss:";
    } else {
      realUrl = "ws:";
    }
    realUrl += "//" + loc.host + url;
  }

  if(protocol == '') protocol == null;
  let socketInfo = null;
  for(let i=0;i<gWebSocketMgr.socketInfoList.length;i++) {
    if(gWebSocketMgr.socketInfoList[i].url == realUrl && gWebSocketMgr.socketInfoList[i].protocol == protocol) {
      socketInfo = gWebSocketMgr.socketInfoList[i];
      break;
    }
  }
  let resultSocket = {
    socketInfo: null,
    ontextmessage: null,
    onbinarymessage: null,
    onmessage: null,
    onopenListener: null,
    get onopen() {return this.onopenListener;},
    set onopen(listener) {
      this.onopenListener = listener;
      if(listener && this.socketInfo.connected) {
        listener(this.socketInfo.onopenEvent);
      }
    },
    onclose: null,
    onerror: null,
    get connected() {
      return this.socketInfo.connected;
    },
    send(msg) {
      try {
        if(this.socketInfo.connected) {
          this.socketInfo.socket.send(msg);
        }
      } catch (e) {
        console.log(e);
      }
    },
    close() {
      for(let i=0;i<this.socketInfo.handlerList.length;i++) {
        if(this.socketInfo.handlerList[i] == this) {
          if(i != (this.socketInfo.handlerList.length - 1)) {
            this.socketInfo.handlerList[i] = this.socketInfo.handlerList[this.socketInfo.handlerList.length - 1];
          }
          this.socketInfo.handlerList.pop();
          break;
        }
      }
      if(this.socketInfo.handlerList.length == 0) {
        if(this.socketInfo.connected) {
          this.socketInfo.socket.close();
        }
      }
    },
  };

  if(socketInfo == null || socketInfo.socket == null) {
    try{
      if(socketInfo == null) {
        socketInfo = {
          url: realUrl,
          protocol: protocol,
          socket: null,
          connected: false,
          onopenEvent: null,
          handlerList: [],
        };
        gWebSocketMgr.socketInfoList.push(socketInfo);
      }
      if(protocol) {
        socketInfo.socket = new WebSocket(realUrl,protocol);
      } else {
        socketInfo.socket = new WebSocket(realUrl);
      }
      if(socketInfo.socket == null) return null;
      socketInfo.socket.onopen = (e)=>{
        socketInfo.connected = true;
        socketInfo.onopenEvent = e;
        socketInfo.handlerList.forEach((handler)=>{
          if(handler.onopen) {
            handler.onopen(e);
          }
        });
        console.log(e);
      };
      socketInfo.socket.onmessage = (e)=>{
        if(typeof(e.data) == 'string') {
          //不要删除，用以跟踪问题
          console.log('WebSocket Message:' + e.data);
        }
        socketInfo.handlerList.forEach((handler)=>{
          if(handler.onmessage) {
            handler.onmessage(e);
          }
          if(handler.ontextmessage && typeof(e.data) == 'string') {
            handler.ontextmessage(e.data);
          } else if(handler.onbinarymessage && e.data instanceof ArrayBuffer) {
            handler.onbinarymessage(e.data);
          }
        });
      };
      socketInfo.socket.onclose = (e)=>{
        socketInfo.connected = false;
        socketInfo.handlerList.forEach((handler)=>{
          if(handler.onclose) {
            handler.onclose(e);
          }
        });
        socketInfo.socket = null;
        console.log(e);
      };
      socketInfo.socket.onerror = (e)=>{
        socketInfo.handlerList.forEach((handler)=>{
          if(handler.onerror) {
            handler.onerror(e);
          }
        });
        console.log(e);
      };
    } catch(e) {
      console.log(e);
      return null;
    }
  }
  resultSocket.socketInfo = socketInfo;
  socketInfo.handlerList.push(resultSocket);
  return resultSocket;
}
